package com.ccit.employee.controller;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ccit.common.baiduFace.constant.FaceConstant;
import com.ccit.common.baiduFace.constant.ImageTypeEnum;
import com.ccit.common.baiduFace.exception.BizException;
import com.ccit.common.baiduFace.pojo.ImageU;
import com.ccit.common.baiduFace.result.FaceResult;
import com.ccit.common.baiduFace.service.FaceManage;
import com.ccit.common.baiduFace.util.FaceUtil;
import com.ccit.common.exception.GymException;
import com.ccit.common.result.Result;
import com.ccit.common.utils.PageUtil;
import com.ccit.common.utils.RedisUtils;
import com.ccit.employee.service.AttendanceService;
import com.ccit.employee.service.EmployeeService;
import com.ccit.model.Attendance;
import com.ccit.model.Employee;
import com.ccit.model.vo.attendance.AttendanceVo;
import com.ccit.model.vo.employee.EmployeeAttendanceVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Component
@RestController
@EnableScheduling
@Api(tags = "考勤管理")
@RequestMapping("/attendance")
public class AttendanceController {

    @Autowired
    private AttendanceService attendanceService;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private RedisUtils redisUtils;

    @ApiOperation("获取员工打卡情况")
    @GetMapping("/getAllAttendance/{current}/{size}/{startTime}/{endTime}")
    public Result getAllAttendance(@PathVariable Integer current,
                                   @PathVariable Integer size,
                                   @PathVariable String startTime,
                                   @PathVariable String endTime) {

        List<AttendanceVo> attendanceVos = new ArrayList<>();
        String key1 = "allAttendance:"+ startTime + ":" + endTime;
        boolean has = redisUtils.hasKey(key1);
        if (has) {
            attendanceVos = (List<AttendanceVo>)redisUtils.get(key1);
        } else {
            List<Employee> employeeList = employeeService.list();
            List<AttendanceVo> attendanceVoss = new ArrayList<>();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String[] split = endTime.split("-");
            split[2] = Integer.toString(Integer.valueOf(split[2]) + 1);

            endTime = split[0] + "-" + split[1] + "-" + split[2];
            try {
                Date start = (Date) sdf.parseObject(startTime);
                Date end = (Date) sdf.parseObject(endTime);
                for (Employee employee : employeeList) {
                    QueryWrapper<Attendance> wrapper = new QueryWrapper<Attendance>();
                    wrapper.lambda()
                            .eq(Attendance::getName, employee.getName())
                            .ge(Attendance::getDate, start)
                            .le(Attendance::getDate, end);

                    List<Attendance> list = attendanceService.list(wrapper);
                    if (list == null) {
                        throw new GymException(202, "时间错误超出范围");
                    }

                    System.out.println(list);
                    //在时间内打卡成功的计数
                    Map<Integer, List<Attendance>> collect = list.stream().collect(Collectors.groupingBy(attendance -> attendance.getClockIn()));

                    Map<Integer, List<String>> collectDate = new HashMap<>();

                    collect.forEach((key, value) -> {
                        List<String> dates = new ArrayList<>();
                        value.forEach(a -> {
                            dates.add(sdf.format(a.getDate()));
                        });
                        collectDate.put(key, dates);
                    });


                    int countClockIn = 0;
                    int countClockOut = 0;
                    if (collectDate.containsKey(1)) {
                        countClockIn = collect.get(1).size();
                    } else {
                        collectDate.put(1, new ArrayList<>());
                    }
                    if (collectDate.containsKey(0)) {
                        countClockOut = collect.get(0).size();
                    } else {
                        collectDate.put(0, new ArrayList<>());
                    }
                    //考勤天数
                    int attendanceDay = countClockIn + countClockOut;

                    //考勤率
                    double clockInRate;
                    double clockOutRate;
                    if (countClockIn == 0 && countClockOut != 0) {
                        clockInRate = 0;
                        clockOutRate = 1.0;
                    } else if (countClockIn != 0 && countClockOut == 0) {
                        clockInRate = 1;
                        clockOutRate = 0;
                    } else if (countClockIn == 0 && countClockOut == 0) {
                        clockInRate = 0;
                        clockOutRate = 0;
                    } else {
                        clockInRate = ((double) countClockIn / attendanceDay);
                        clockOutRate = ((double) countClockOut / attendanceDay);
                    }
                    //封装
                    AttendanceVo attendanceVo = new AttendanceVo();
                    attendanceVo.setEmployeeId(employee.getId());
                    attendanceVo.setName(employee.getName());
                    attendanceVo.setAttendCount(attendanceDay);
                    attendanceVo.setClockInRate(clockInRate);
                    attendanceVo.setClockOutRate(clockOutRate);
                    attendanceVo.setCollect(collectDate);
                    attendanceVoss.add(attendanceVo);
                }
                attendanceVos = attendanceVoss;
                redisUtils.set(key1,attendanceVos);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        Page page = PageUtil.getPages(current, size, attendanceVos);
        return Result.ok(page);

    }


    @ApiOperation("分页获取员工考勤信息")
    @GetMapping("/getByPage/{current}/{size}")
    public Result getEmployeeByPage(@PathVariable Integer current, @PathVariable Integer size) {
        Page<Attendance> page;
        String key = "attendancePage:"+ current + ":" + size;
        boolean has = redisUtils.hasKey(key);
        if (has) {
            page = (Page<Attendance>)redisUtils.get(key);
        } else {
            QueryWrapper<Attendance> wrapper = new QueryWrapper<Attendance>();
            wrapper.lambda()
                    .orderByDesc(Attendance::getDate);
            Page<Attendance> attendancePage = new Page<>(current, size);
            page = attendanceService.page(attendancePage, wrapper);
            redisUtils.set(key,page,60*120*24*7);
        }
        return Result.ok(page);
    }

    @ApiOperation("分页获取当天员工考勤信息")
    @GetMapping("/getByTodayPage/{current}/{size}")
    public Result getTodayAttendanceByPage(@PathVariable Integer current, @PathVariable Integer size) {
        Page<Attendance> page;
        String key = "attendanceToDayPage:"+ current + ":" + size;
        boolean has = redisUtils.hasKey(key);
        if (has) {
            page = (Page<Attendance>)redisUtils.get(key);
        } else {
            String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            QueryWrapper<Attendance> wrapper = new QueryWrapper<Attendance>();
            wrapper.lambda()
                    .likeRight(Attendance::getDate, format)
                    .orderByDesc(Attendance::getDate);
            List<Attendance> list = attendanceService.list(wrapper);
            Map<Long, List<Attendance>> listMap = list.stream().collect(Collectors.groupingBy(Attendance::getEmployeeId));

            List<Employee> employeeList = employeeService.list();

            List<EmployeeAttendanceVo> employeeAttendanceVos = new ArrayList<>();
            employeeList.forEach(employee -> {
                EmployeeAttendanceVo employeeAttendanceVo = new EmployeeAttendanceVo();
                employeeAttendanceVo.setId(employee.getId());
                employeeAttendanceVo.setName(employee.getName());
                employeeAttendanceVo.setClockIn(listMap.get(employee.getId()).get(0).getClockIn());
                employeeAttendanceVo.setDate(listMap.get(employee.getId()).get(0).getDate());
                employeeAttendanceVo.setPhone(employee.getPhone());
                employeeAttendanceVo.setType(employee.getType());
                employeeAttendanceVos.add(employeeAttendanceVo);
            });
            page = PageUtil.getPages(current, size, employeeAttendanceVos);
            redisUtils.set(key,page);
        }

        return Result.ok(page);
    }


    @Scheduled(cron = "0 0 3 * * ? ")//每天3点
    @ApiOperation("创建当天员工考勤信息")
    @PostMapping("/saveAttendance")
    public Result saveAttendence() {
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        QueryWrapper<Attendance> wrapper = new QueryWrapper<Attendance>();
        wrapper.lambda()
                .likeRight(Attendance::getDate, format)
                .orderByDesc(Attendance::getDate);
        List<Attendance> attendanceList = attendanceService.list(wrapper);
        if (attendanceList.size() == 0) {
            List<Employee> list = employeeService.list();
            list.forEach(employee -> {
                Attendance attendance = new Attendance();
                attendance.setEmployeeId(employee.getId());
                attendance.setName(employee.getName());
                attendance.setType(employee.getType());
                attendance.setPhone(employee.getPhone());
                attendanceService.save(attendance);
            });
            redisUtils.deleteRedisKeys("allAttendance");
            redisUtils.deleteRedisKeys("attendancePage");
            redisUtils.deleteRedisKeys("attendanceToDayPage");
            redisUtils.deleteRedisKeys("AttendanceYear");
            redisUtils.deleteRedisKeys("employeePage");
            redisUtils.deleteRedisKeys("allEmployee");
            redisUtils.deleteRedisKeys("coachList");
            redisUtils.deleteRedisKeys("maintainerList");
            return Result.ok();
        } else return Result.ok();

    }

    //百度api//
    @ApiOperation("人脸签到")
    @PostMapping("/clockByFace")
    public Result clockByFace(@RequestPart MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            throw new BizException("上传文件不能为空");
        }
        String groupIds = "employee";
        String data = FaceUtil.encodeBase64(file.getBytes());
        ImageU imageU = ImageU.builder().data(data).imageTypeEnum(ImageTypeEnum.BASE64).build();
        FaceResult result = FaceManage.faceSearch(groupIds, imageU);
        String users = result.getData().getString(FaceConstant.USER_LIST);
        if (StringUtils.isEmpty(users)) {
            throw new GymException(401, "人脸认证失败");
        }
        JSONArray array = JSONObject.parseArray(users);
        JSONObject object = JSONObject.parseObject(array.get(0).toString());
        Integer score = object.getInteger(FaceConstant.SCORE);
        Long employeeId = object.getLong("user_id");
        JSONObject userInfo=JSONObject.parseObject(object.getString("user_info"));
        if (score == null) {
            throw new GymException(401, "人脸认证失败");
        }
        if (score >= FaceConstant.MATCH_SCORE) {
            //进行打卡操作
            Date today = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String format = sdf.format(today);
            QueryWrapper<Attendance> wrapper = new QueryWrapper<Attendance>();
            //查询条件为创建时间
            wrapper.lambda()
                    .eq(Attendance::getEmployeeId, employeeId)
                    .likeRight(Attendance::getDate, format)
                    .orderByDesc(Attendance::getDate);

            Attendance one = attendanceService.getOne(wrapper);
            if (one != null) {
                if (one.getClockIn() == 1) {
                    return Result.ok("已打卡");
                } else one.setClockIn(1);
                boolean flag = attendanceService.updateById(one);
                if (flag) {
                    redisUtils.deleteRedisKeys("allAttendance");
                    redisUtils.deleteRedisKeys("attendancePage");
                    redisUtils.deleteRedisKeys("attendanceToDayPage");
                    redisUtils.deleteRedisKeys("AttendanceYear");
                    redisUtils.deleteRedisKeys("employeePage");
                    redisUtils.deleteRedisKeys("allEmployee");
                    redisUtils.deleteRedisKeys("coachList");
                    redisUtils.deleteRedisKeys("maintainerList");
                    return Result.ok("员工" + userInfo.getString("user") + "验证成功,完成打卡");
                } else throw new GymException(203, "服务异常");
            } else throw new GymException(204, "查无此人");
        }
        throw new GymException(401, "人脸认证失败");
    }
    //百度api//


    @ApiOperation("员工打卡")
    @PostMapping("/clock")
    public Result clock(@RequestBody Attendance attendance) {
        System.out.println(attendance.getDate() + "===========================================");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String format = sdf.format(attendance.getDate());

        QueryWrapper<Attendance> wrapper = new QueryWrapper<Attendance>();
        //查询条件为创建时间
        wrapper.lambda()
                .eq(Attendance::getEmployeeId, attendance.getEmployeeId())
                .likeRight(Attendance::getDate, format)
                .orderByDesc(Attendance::getDate);

        Attendance one = attendanceService.getOne(wrapper);
        if (one != null) {
            if (one.getClockIn() == 1) {
                return Result.ok("已打卡");
            } else one.setClockIn(1);
            boolean flag = attendanceService.updateById(one);
            if (flag) {
                redisUtils.deleteRedisKeys("allAttendance");
                redisUtils.deleteRedisKeys("attendancePage");
                redisUtils.deleteRedisKeys("attendanceToDayPage");
                redisUtils.deleteRedisKeys("AttendanceYear");
                redisUtils.deleteRedisKeys("employeePage");
                redisUtils.deleteRedisKeys("allEmployee");
                redisUtils.deleteRedisKeys("coachList");
                redisUtils.deleteRedisKeys("maintainerList");
                return Result.ok();
            } else throw new GymException(203, "服务异常");
        } else throw new GymException(204, "查无此人");

    }


    /**
     * 修改考勤
     */
    @ApiOperation("修改考勤")
    @PostMapping("/update")
    public Result update(@RequestBody Attendance attendance) {
        QueryWrapper<Attendance> wrapper = new QueryWrapper<Attendance>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String format = sdf.format(attendance.getDate());
        //查询条件为创建时间
        wrapper.lambda()
                .eq(Attendance::getEmployeeId, attendance.getEmployeeId())
                .likeRight(Attendance::getDate, format)
                .orderByDesc(Attendance::getDate);

        Attendance one = attendanceService.getOne(wrapper);
        if (one == null) {
            throw new GymException(202, "参数错误");
        }

        if (one.getClockIn() == 0) {
            one.setClockIn(1);
        } else one.setClockIn(0);

        attendanceService.updateById(one);
        redisUtils.deleteRedisKeys("allAttendance");
        redisUtils.deleteRedisKeys("attendancePage");
        redisUtils.deleteRedisKeys("attendanceToDayPage");
        redisUtils.deleteRedisKeys("AttendanceYear");
        redisUtils.deleteRedisKeys("employeePage");
        redisUtils.deleteRedisKeys("allEmployee");
        redisUtils.deleteRedisKeys("coachList");
        redisUtils.deleteRedisKeys("maintainerList");
        return Result.ok(one);
    }

    @GetMapping("/getYear")
    @ApiOperation(value = "查询5年之前订单")
    public Result getYear() {

        List<Attendance> list;
        String key = "AttendanceYear";
        boolean has = redisUtils.hasKey(key);
        if (has) {
            list = (List<Attendance>)redisUtils.get(key);
        } else {
            String[] split = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString().split("-");
            QueryWrapper<Attendance> wrapper = new QueryWrapper<>();
            wrapper.lambda()
                    .ge(Attendance::getDate, Integer.valueOf(split[0]) - 5 + "-00-00")
                    .le(Attendance::getDate, Integer.valueOf(split[0]) + 1 + "-00-00")
                    .orderByDesc(Attendance::getDate);

            list = attendanceService.list(wrapper);
            redisUtils.set(key,list);
        }

        return Result.ok(list);


    }

}









